package com.diana.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.Condition;
import com.diana.common.*;
import com.diana.entity.IntegralRecord;
import com.diana.entity.Product;
import com.diana.entity.SeckillSuccessRecord;
import com.diana.entity.User;
import com.diana.mapper.ProductMapper;
import com.diana.service.*;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.*;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Transaction;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by anzhi on 2019/9/15.
 */
@RestController
public class CommonController {

    @Autowired
    private RedisTemplate redisTemplate;
    private static String LOG_PATH ="/root/diana/log/";
    private static Logger log = LoggerFactory.getLogger(CommonController.class);
    static {
        String os = System.getProperty("os.name");
        if(os.toLowerCase().startsWith("win")){
            LOG_PATH = "D:"+LOG_PATH;
        }
        log.info("log path:{}",LOG_PATH);
    }

    @RequestMapping("/common/uploadImage")
    public String upload(@RequestParam(required = false,value = "file")MultipartFile file) throws IOException {
        String path = "/diana/manager/image/";
        String fileExtend = Utils.getFileExtend(file);
        String fileName = IDUtil.getId()+"."+fileExtend;
        String url = TxCosUtils.upload(path, file.getInputStream(), fileName);
        if(Utils.isNullOrEmpty(url)){
            return Utils.message("0001","上传文件失败",null);
        }
        return Utils.message("0000","上传文件成功",url);
    }

    @RequestMapping("/admin/common/getSystemLog")
    public String getSystemLog(@RequestBody Map<String,Object> map){

        String logName = Utils.toString(map.get("logName"));
        if(Utils.isNullOrEmpty(logName)){
            logName = "logback."+ LocalDate.now()+".log";
        }
        logName = LOG_PATH+logName;
        String res = "";
        try {
            /*File file = ResourceUtils.getFile(PATH+"logback."+ LocalDate.now()+".log");
            InputStream is = new FileInputStream(file);
            res = IOUtils.toString(is);*/
            Path path = Paths.get(logName);
            byte [] bytes = Files.readAllBytes(path);
            res = new String(bytes, StandardCharsets.UTF_8);
        } catch (IOException e) {
            log.error("========getSystemLog IOException========",e);
            return Utils.message("0001","获取异常",null);
        }
        return Utils.message("0000","成功",res);
    }

    @RequestMapping("/admin/common/getSystemLogList")
    public String getSystemLogList(){

        List<Map<String,Object>> list = new ArrayList<>();
        Path dir = Paths.get(LOG_PATH);
        if(dir!=null){
            try(DirectoryStream<Path> stream = Files.newDirectoryStream(dir)){
                Map<String,Object> map = null;
                for(Path e:stream){
                    map = new HashMap<>();
                    map.put("logName",e.getFileName().toString());
                    list.add(map);
                }
            } catch (IOException e) {
                log.error("========getSystemLogList IOException========",e);
                return Utils.message("0001","获取异常",null);
            }
        }
        return Utils.message("0000","获取成功",list);
    }

    @Autowired
    private QueueMainService queueMainService;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserService userService;
    @Autowired
    private IntegralRecordService integralRecordService;
    @Autowired
    private SeckillSuccessRecordService seckillSuccessRecordService;
    @Autowired
    private ProductMapper productMapper;

    @RequestMapping("/common/putProduct")
    public String putProduct(String productName,Integer num){
        String productId = null;
        Product selectOne = productService.selectOne(Condition.create().eq("productName", productName));
        if(selectOne==null){
            productId = queueMainService.getQueueValue("productId");
            Product product = new Product();
            product.setProductId(productId);
            product.setProductName(productName);
            product.setNum(num);
            productService.insert(product);
        }else{
            productId = selectOne.getProductId();
            Product product = new Product();
            product.setProductId(productId);
            product.setNum(num+selectOne.getNum());
            productService.insertOrUpdate(product);
        }
        String key = productId+":Num";
        Integer integer = Utils.toInteger(redisTemplate.opsForValue().get(key));
        if(integer!=null){
            num = integer+num;
        }
        redisTemplate.opsForValue().set(key,num);
        return Utils.message("0000","操作成功,商品"+productId+"库存:"+Utils.toInteger(redisTemplate.opsForValue().get(key)),null);
    }

    @RequestMapping("/common/putUser1")
    public String putUser(){
        List<User> list = new ArrayList<>();
        User user = null;
        String userId = null;
        for(int i=0;i<10000;i++){
            user = new User();
            userId = queueMainService.getQueueValue("userId");
            user.setUserId(userId);
            user.setUserName("user"+i);
            user.setIntegral((int) (Math.random()*1000)+1);
            list.add(user);
        }
        boolean b = userService.insertBatch(list);
        if(b){
            return Utils.message("0000","操作成功",null);
        }
        return Utils.message("0001","操作失败",null);
    }

    @RequestMapping("/common/seckill")
    @Transactional
    public String seckill(String productId,String userId){
        Jedis jedis = JedisUtils.getJedis();
        try {
            String key = productId+":Num";
            Integer integer = Utils.toInteger(jedis.get(key));
            if(integer==null||integer<=0){
                return Utils.message("0001","库存不足",null);
            }
            User user = userService.selectById(userId);
            Integer integral = user.getIntegral();
            if(integral<100){
                return Utils.message("0001","积分不足",null);
            }
            String successKey =productId+":success:"+userId;
            Integer success = Utils.toInteger(jedis.get(successKey));
            if(success!=null&&success==1){
                return Utils.message("0001","您已抢购成功，无需多次抢购!",null);
            }

            //使用WATCH监控的key如果发生了变化，事务将被打断
            jedis.watch(key);
            //标记一个事务的开始
            Transaction multi = jedis.multi();
            multi.set(successKey,"1");
            multi.decr(key);
            //修改用户积分
            user = new User();
            user.setUserId(userId);
            user.setIntegral(integral-100);
            //插入秒杀成功记录表
            SeckillSuccessRecord seckillSuccessRecord = new SeckillSuccessRecord();
            seckillSuccessRecord.setProductId(productId);
            seckillSuccessRecord.setUserId(userId);
            seckillSuccessRecord.setStatus(1);
            //插入积分记录表
            IntegralRecord integralRecord = new IntegralRecord();
            integralRecord.setFormerIntegral(integral);
            integralRecord.setIntegralNum(100);
            integralRecord.setCurrentIntegral(integral-100);
            integralRecord.setStatus(0);
            integralRecord.setUserId(userId);
            //修改商品库存
            int updateProductNum = productMapper.updateProductNum(productId);

            boolean insertIntegralRecord= integralRecordService.insert(integralRecord);
            boolean insertseckillSuccessRecord = seckillSuccessRecordService.insert(seckillSuccessRecord);
            boolean updateUser = userService.updateById(user);
            //执行事务  源码中有可能返回null
            List exec = multi.exec();
            if(exec==null){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return Utils.message("0001","抢购失败!",null);
            }
            if(insertIntegralRecord&&insertseckillSuccessRecord&&updateProductNum>0&&updateUser&&exec.size()>0){
                return Utils.message("0000","恭喜您，抢购成功!",null);
            }else if(exec.size()>0){
                jedis.incr(key);
                jedis.del(successKey);
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return Utils.message("0001","抢购失败!",null);
            }
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Utils.message("0001","抢购失败!",null);
        }catch (Exception e){
            log.error(" seckill exception ",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Utils.message("0001","系统异常",null);
        }finally {
            JedisUtils.returnJedis(jedis);
        }
    }

    /*@Autowired
    private RabbitTemplate rabbitTemplate;

    @RequestMapping("/sentQueue")
    public String sentQueue(String msg){
        if(Utils.isNullOrEmpty(msg)){
            return Utils.message("0001","msg为空",null);
        }
        JSONObject json = new JSONObject();
        json.put("name","安之");
        json.put("content","测试内容");
        long id = IDUtil.getId();
        Message message = MessageBuilder.withBody(json.toJSONString().getBytes()).setContentType("UTF-8").setMessageId(id+"").build();
        CorrelationData correlationData = new CorrelationData(id+"");
        rabbitTemplate.convertSendAndReceive("diana_exchange","diana.test",message,correlationData);
        return Utils.message("0000","消息发送成功",null);
    }*/

    /*@RabbitListener(queues = "diana_queue")
    @RabbitHandler
    public void readQueue(String msg, Channel channel,Message message) throws IOException {
        try{
            String messageId = message.getMessageProperties().getMessageId();
            String msgs =new String(message.getBody(),"UTF-8");
            String a = null;
            a.length();
            log.info("msg:"+msg);
            log.info("msgs:"+msgs);
            log.info(messageId);
            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        }catch (Exception e){
            log.info("消息消费失败!!!");
        }
    }*/


    /*@Autowired
    private RocketmqProducer rocketmqProducer;

    @RequestMapping("/sentRocketmq")
    public String sentRocketmq(String msg) throws RemotingException, MQClientException, InterruptedException {
        org.apache.rocketmq.common.message.Message message =
                new org.apache.rocketmq.common.message.Message("dianaboot","tag1",msg.getBytes());
        rocketmqProducer.getProducer().send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("发送成功");
                log.info(JSONObject.toJSONString(sendResult));
            }

            @Override
            public void onException(Throwable throwable) {
                log.info("发送失败");
            }
        });
        return "成功";
    }*/

    @Autowired
    private DefaultMQProducer defaultMQProducer;

    @RequestMapping("/sentRocketmq")
    public String sentRocketmq(String msg) throws RemotingException, MQClientException, InterruptedException {
        org.apache.rocketmq.common.message.Message message =
                new org.apache.rocketmq.common.message.Message("dianaboot","tag1",msg.getBytes());
        transactionMQProducer.send(message, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                log.info("发送成功");
                log.info(JSONObject.toJSONString(sendResult));
            }

            @Override
            public void onException(Throwable throwable) {
                log.info("发送失败");
            }
        });
        return "成功";
    }

    @Autowired
    private TransactionMQProducer transactionMQProducer;

    @RequestMapping("/sentTransactionRocketmq")
    public String sentTransactionRocketmq(String msg) throws RemotingException, MQClientException, InterruptedException {
        org.apache.rocketmq.common.message.Message message =
                new org.apache.rocketmq.common.message.Message("dianaboot","tag1",msg.getBytes());
        TransactionSendResult sendResult = transactionMQProducer.sendMessageInTransaction(message, null);
        SendStatus sendStatus = sendResult.getSendStatus();
        log.info(sendResult.getLocalTransactionState().name());
        if(sendStatus.name().equals("SEND_OK")){
            return Utils.message("0000","消息发送成功,请稍后查看结果",null);
        }
        return Utils.message("0001","消息发送失败,请联系管理员",null);
    }



    @RequestMapping("/common/jedisTest")
    public String jedisTest(){
        Jedis jedis = JedisUtils.getJedis();
        try{
            String key = "jedisTest";
            String value = "jedisTestValue";
            Long setnx = jedis.setnx(key, value);
            if(setnx>0){
                jedis.expire(key,60);
            }
            return Utils.message("0000","成功",setnx);
        }catch (Exception e){
            log.info("jedisTest error {}",e);
            return Utils.message("0000","失败",null);
        }finally {
            JedisUtils.returnJedis(jedis);
        }
    }


    @RequestMapping("/common/tryRedisLock")
    public String tryRedisLock(String managerId){
        String requestId = IDUtil.getId()+"";
        boolean b = RedisLock.tryRedisLock(managerId, requestId, 10000);
        return Utils.message("0000","操作成功",b);
    }

    @RequestMapping("/common/releaseRedisLock")
    public String releaseRedisLock(String managerId,String requestId){
        boolean b = RedisLock.releaseRedisLock(managerId,requestId);
        return Utils.message("0000","操作成功",b);
    }

    @Value("${xxl.job.admin.addresses}")
    String xxlJobUrl;
    @Value("${druidUrl}")
    String druidUrl;

    @RequestMapping("/admin/common/getXxlJobUrl")
    public String getXxlJobUrl(){
        return Utils.message("0000","获取成功",xxlJobUrl);
    }

    @RequestMapping("/admin/common/getDruidUrl")
    public String getDruidUrl(){
        return Utils.message("0000","获取成功",druidUrl);
    }
}
